/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package assignment2;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

/**
 * SCMSGUI Class:
 * This is the main runtime class, which contains the main method, as well as object creation
 * @author Vale
 *
 */
public class SCMSGUI implements ActionListener, WindowListener {

    /**
     * @param args the command line arguments
     */
    private JFrame mainFrame;
    private JPanel contentPanel;
    private JPanel northPanel;
    private JPanel centralPanel;
    private JButton viewProd = new JButton(MAIN_OPT1);
    private JButton viewInvent = new JButton(MAIN_OPT2);
    private JButton schedProd = new JButton(MAIN_OPT3);
    private JButton readFile = new JButton(MAIN_OPT4);
    private JButton writeFile = new JButton(MAIN_OPT5);
    private JButton exitGUI = new JButton(MAIN_OPT0);
    private ProductList prodList = new ProductList();
    private InventoryList invList = new InventoryList();
    private static final String MAIN_OPT0 = "0. Exit";
    private static final String MAIN_OPT1 = "1. View/Edit Products";
    private static final String MAIN_OPT2 = "2. View/Edit Current Inventory";
    private static final String MAIN_OPT3 = "3. Schedule Products for Manufacturing";
    private static final String MAIN_OPT4 = "4. Read Current Products/Inventory from File";
    private static final String MAIN_OPT5 = "5. Save Current Products/Inventory to File";
    private static final String PROMPT_QUEST = "Save Changes?";
    private static final String PROMPT_TITLE = "Select an Option";
    private static final String FRAME_HEADING = "Supply Chain Management System";
    private static final String GUI_TITLE = "SCMS Interface";
    private static final String GUI_TITLE_NAME = "By: Michael Vale";
    private static final String HEADING_FONT = "Heading";
    private static final String ERROR = "Error";
    private static final String IOERR_TITLE = "IO Error";
    private static final String FILE_NAME = "E:\\SCMSInfo.xml";
    private static final int HEADING_FONT_SIZE = 20;
    private static final int NPANEL_ROWS = 4;
    private static final int NPANEL_COLS = 1;
    private static final int CPANEL_ROWS = 6;
    private static final int CPANELS_COLS = 1;
    private static final int BUTTON_SPACING = 10;
    private static final int FRAME_WIDTH = 400;
    private static final int FRAME_HEIGHT = 500;
    private static final int NO_OPT = 1;

    /**^
     * void actionPerformed(ActionEvent e) Method:
     * This is called when the "Exit" button is pressed. It creates a new WindowEvent that notifies the class that mainFrame is closing, which in turn prompts the user to save. It also
     * calls System.exit(0), such that the program is terminated and memory is released back to the system.
     *
     */
    public void actionPerformed(ActionEvent e) {
        WindowEvent w = new WindowEvent(mainFrame, WindowEvent.WINDOW_CLOSING);
        windowClosing(w);
        System.exit(0);
    }

    /**
     * void windowOpened(WindowEvent e) Method:
     * This is one of the abstract methods of the WindowListener class. It has not been implemented.
     *
     */
    public void windowOpened(WindowEvent e) {
    }

    /**
     * void windowClosing(WindowEvent e) Method:
     * This is one of the abstract methods of the WindowListener class. It has been used in this case to alert the user that they are exiting the program, and as such,
     * ask if they would like to save the data they have added/modified, to disk.
     *
     */
    public void windowClosing(WindowEvent e) {
        int opt = JOptionPane.showConfirmDialog(mainFrame, PROMPT_QUEST, PROMPT_TITLE, JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
        if (opt == NO_OPT) {
            mainFrame.dispose();
        } else {
            try {
                new ExternalFileWriter(prodList, invList);
            } catch (IOException ex) {
                JOptionPane.showMessageDialog(mainFrame, IOERR_TITLE, ERROR, JOptionPane.ERROR_MESSAGE);
                return;
            }
        }
    }

    /**
     * void windowClosed(WindowEvent e) Method:
     * This is one of the abstract methods of the WindowListener class. It has not been implemented, as its purpose has been covered by the 'windowClosing' event.
     *
     */
    public void windowClosed(WindowEvent e) {
    }

    /**
     * void windowIconified(WindowEvent e) Method:
     * This is one of the abstract methods of the WindowListener class. It has not been implemented.
     *
     */
    public void windowIconified(WindowEvent e) {
    }

    /**
     * void windowDeiconified(WindowEvent e) Method:
     * This is one of the abstract methods of the WindowListener class. It has not been implemented.
     *
     */
    public void windowDeiconified(WindowEvent e) {
    }

    /**
     * void windowActivated(WindowEvent e) Method:
     * This is one of the abstract methods of the WindowListener class. It has not been implemented.
     *
     */
    public void windowActivated(WindowEvent e) {
    }

    /**
     * void windowDeactivated(WindowEvent e) Method:
     * This is one of the abstract methods of the WindowListener class. It has not been implemented.
     *
     */
    public void windowDeactivated(WindowEvent e) {
    }

    /**
     * ViewProducts Inner Class:
     * This inner class is used as a listener to the "View Products" button. It instantiates a new instance of the ProductViewer class when the button is pressed, such
     * that all products and their respective information is shown.
     *
     */
    public class ViewProducts implements ActionListener {

        public void actionPerformed(ActionEvent e) {
            new ProductViewer(prodList,invList);
        }
    }

    /**
     * ViewInventory Inner Class:
     * This inner class is used as a listener to the "View Inventory" button. It instantiates a new instance of the InventoryViewer class when the button is pressed, such
     * that a new Product can be added to the list.
     *
     */
    public class ViewInventory implements ActionListener {

        public void actionPerformed(ActionEvent e) {
            new InventoryViewer(invList, prodList);
        }
    }

    /**
     * ScheduleProducts Inner Class:
     * This inner class is used as a listener to the "Schedule Products" button. It instantiates a new instance of the ProductSchedule class when the button is pressed, such
     * that the number of products for manufacturing can be scheduled.
     *
     */
    public class ScheduleProducts implements ActionListener {

        public void actionPerformed(ActionEvent e) {
            new ProductSchedule(prodList, invList);
        }
    }

    /**
     * ReadFile Inner Class:
     * This inner class is used as a listener to the "Read File" button. It instantiates a new instance of the ExternalFileReader class when the button is pressed, such
     * that all inventory/product information is read from an external file.
     *
     */
    public class ReadFile implements ActionListener {

        public void actionPerformed(ActionEvent e) {
            try {
                new ExternalFileReader(prodList, invList);
            } catch (IOException ex) {
                JOptionPane.showMessageDialog(mainFrame, IOERR_TITLE, ERROR, JOptionPane.ERROR_MESSAGE);
                return;
            } catch (NullPointerException ex) {
                File externalFile = new File(FILE_NAME);
                try {
                    externalFile.createNewFile();
                } catch (IOException exc) {
                    JOptionPane.showMessageDialog(mainFrame, IOERR_TITLE, ERROR, JOptionPane.ERROR_MESSAGE);
                }
            }
        }
    }

    /**
     * WriteFile Inner Class:
     * This inner class is used as a listener to the "Write File" button. It instantiates a new instance of the ExternalFileWriter class when the button is pressed, such
     * that all current inventory and product data is written to an external file.
     *
     */
    public class WriteFile implements ActionListener {

        public void actionPerformed(ActionEvent e) {
            try {
                new ExternalFileWriter(prodList, invList);
            } catch (IOException ex) {
                JOptionPane.showMessageDialog(mainFrame, IOERR_TITLE, ERROR, JOptionPane.ERROR_MESSAGE);
                return;
            }
        }
    }

    /**
     * static void main(String[] args) Method:
     * Main Method - Starts Program
     *
     */
    public static void main(String[] args) {
        // TODO code application logic here
        SCMSGUI newSCMS = new SCMSGUI();
        newSCMS.startSCMS();
    }

    /**
     * static void startSCMS() Method:
     * Initialises all Objects in Product and Inventory Array, before printing main menu
     *
     */
    public void startSCMS() {
////        ProductList pl = new ProductList();
//        Product testProd = new Product();
//        Inventory testInv = new Inventory();
//        testInv.setInvName("Test Invent");
//        testInv.setInvStock(0);
//        testInv.setInvUnits("kg");
////        InventoryList il = new InventoryList();
//        //TODO Read Inventory from File
//        //TODO Read Products from File
//        testProd.setProdName("Test");
//        testProd.setProdSched(100);
//        testProd.getInventList().add(testInv);
//        prodList.add(testProd);
//        Product testProd1 = new Product();
//        Inventory testInv1 = new Inventory();
//        testInv1.setInvName("Test Invent222");
//        testInv1.setInvStock(2);
//        testInv1.setInvUnits("kg");
//        testProd1.setProdName("Test1");
//        testProd1.setProdSched(200);
//        testProd1.getInventList().add(testInv1);
//        prodList.add(testProd1);
//        invList.add(testInv);
//        invList.add(testInv1);
//        int testProdlist = prodList.getProdList().size();
        printMain();
    }

    /**
     * void printMain() Method:
     * Used to set up and print the main screen
     *
     */
    public void printMain() {
        // Create Panels
        mainFrame = new JFrame(FRAME_HEADING);
        contentPanel = new JPanel();
        northPanel = new JPanel();
        centralPanel = new JPanel();

        // Set up Buttons for use
        viewProd.addActionListener(new ViewProducts());
        viewInvent.addActionListener(new ViewInventory());
        schedProd.addActionListener(new ScheduleProducts());
        readFile.addActionListener(new ReadFile());
        writeFile.addActionListener(new WriteFile());
        exitGUI.addActionListener(this);

        //Set up the North Panel - Used for GUI Heading
        northPanel.setLayout(new GridLayout(NPANEL_ROWS, NPANEL_COLS));
        JLabel northHead = new JLabel(GUI_TITLE);
        formatHeading(northHead);
        JLabel southHead = new JLabel(GUI_TITLE_NAME);
        formatHeading(southHead);
        northPanel.add(northHead);
        northPanel.add(southHead);

        //Set up Central Panel - Used for displaying buttons
        centralPanel.setLayout(new GridLayout(CPANEL_ROWS, CPANELS_COLS, BUTTON_SPACING, BUTTON_SPACING));
        centralPanel.add(viewProd);
        centralPanel.add(viewInvent);
        centralPanel.add(schedProd);
        centralPanel.add(readFile);
        centralPanel.add(writeFile);
        centralPanel.add(exitGUI);

        //Set up Main Panel
        contentPanel.setLayout(new BorderLayout());
        contentPanel.add(northPanel, BorderLayout.NORTH);
        contentPanel.add(centralPanel, BorderLayout.CENTER);

        //Set up frame
        mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        mainFrame.getContentPane().add(contentPanel);
        mainFrame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
        mainFrame.setVisible(true);
    }

    /**
     * void formatHeading(JLabel heading) Method:
     * This method is used to take a given heading label and format it to a certain background colour/font/alignment.
     * @param heading This is the heading that is to be formatted.
     *
     */
    void formatHeading(JLabel heading) {
        Color bgColour = mainFrame.getBackground();
        heading.setBackground(bgColour);
        Font headerFont = new Font(HEADING_FONT, Font.BOLD, HEADING_FONT_SIZE);
        heading.setFont(headerFont);
        heading.setHorizontalAlignment(JLabel.CENTER);
    }
}
